/**
 * 插值变换组件
 * 
 * 职责：
 * 1. 存储逻辑层的位置、旋转、缩放
 * 2. 存储上一帧的状态（用于插值）
 * 3. 提供插值计算方法
 * 
 * 使用场景：
 * - 逻辑系统（20 FPS）更新逻辑位置
 * - 渲染系统（60 FPS）使用插值位置渲染
 * 
 * @author AI Assistant
 * @date 2025-11-26
 */

import { Vec3, Quat } from "cc";
import { ecs } from "db://assets/core/ecs/ECS";

/**
 * 插值变换组件
 */
@ecs.register('InterpolatedTransform')
export class InterpolatedTransform extends ecs.Comp {
    // ========== 当前逻辑状态 ==========
    
    /** 当前位置 */
    position: Vec3 = new Vec3(0, 0, 0);
    
    /** 当前旋转（欧拉角） */
    rotation: Vec3 = new Vec3(0, 0, 0);
    
    /** 当前缩放 */
    scale: Vec3 = new Vec3(1, 1, 1);
    
    // ========== 上一帧逻辑状态（用于插值） ==========
    
    /** 上一帧位置 */
    previousPosition: Vec3 = new Vec3(0, 0, 0);
    
    /** 上一帧旋转 */
    previousRotation: Vec3 = new Vec3(0, 0, 0);
    
    /** 上一帧缩放 */
    previousScale: Vec3 = new Vec3(1, 1, 1);
    
    // ========== 配置 ==========
    
    /** 是否启用位置插值 */
    enablePositionInterpolation: boolean = true;
    
    /** 是否启用旋转插值 */
    enableRotationInterpolation: boolean = true;
    
    /** 是否启用缩放插值 */
    enableScaleInterpolation: boolean = false; // 缩放通常不需要插值
    
    /**
     * 重置组件
     */
    reset(): void {
        this.position.set(0, 0, 0);
        this.rotation.set(0, 0, 0);
        this.scale.set(1, 1, 1);
        
        this.previousPosition.set(0, 0, 0);
        this.previousRotation.set(0, 0, 0);
        this.previousScale.set(1, 1, 1);
        
        this.enablePositionInterpolation = true;
        this.enableRotationInterpolation = true;
        this.enableScaleInterpolation = false;
    }
    
    // ========== 逻辑层更新方法（在逻辑系统中调用） ==========
    
    /**
     * 更新位置（逻辑系统调用）
     */
    setPosition(x: number, y: number, z: number = 0): void {
        // 保存上一帧
        this.previousPosition.set(this.position);
        
        // 更新当前位置
        this.position.set(x, y, z);
    }
    
    /**
     * 设置位置（Vec3）
     */
    setPositionVec3(position: Vec3): void {
        this.previousPosition.set(this.position);
        this.position.set(position);
    }
    
    /**
     * 移动（相对）
     */
    move(dx: number, dy: number, dz: number = 0): void {
        this.setPosition(
            this.position.x + dx,
            this.position.y + dy,
            this.position.z + dz
        );
    }
    
    /**
     * 更新旋转（逻辑系统调用）
     */
    setRotation(x: number, y: number, z: number): void {
        this.previousRotation.set(this.rotation);
        this.rotation.set(x, y, z);
    }
    
    /**
     * 设置旋转（Vec3）
     */
    setRotationVec3(rotation: Vec3): void {
        this.previousRotation.set(this.rotation);
        this.rotation.set(rotation);
    }
    
    /**
     * 旋转（相对）
     */
    rotate(dx: number, dy: number, dz: number): void {
        this.setRotation(
            this.rotation.x + dx,
            this.rotation.y + dy,
            this.rotation.z + dz
        );
    }
    
    /**
     * 更新缩放（逻辑系统调用）
     */
    setScale(x: number, y: number, z: number = 1): void {
        this.previousScale.set(this.scale);
        this.scale.set(x, y, z);
    }
    
    /**
     * 设置缩放（Vec3）
     */
    setScaleVec3(scale: Vec3): void {
        this.previousScale.set(this.scale);
        this.scale.set(scale);
    }
    
    /**
     * 统一缩放
     */
    setUniformScale(scale: number): void {
        this.setScale(scale, scale, scale);
    }
    
    // ========== 插值方法（在渲染系统中调用） ==========
    
    /**
     * 获取插值后的位置
     * @param alpha 插值因子（0-1）
     */
    getInterpolatedPosition(alpha: number): Vec3 {
        if (!this.enablePositionInterpolation || alpha === 0) {
            return this.position.clone();
        }
        
        // 线性插值：result = prev + (current - prev) * alpha
        return new Vec3(
            this.previousPosition.x + (this.position.x - this.previousPosition.x) * alpha,
            this.previousPosition.y + (this.position.y - this.previousPosition.y) * alpha,
            this.previousPosition.z + (this.position.z - this.previousPosition.z) * alpha
        );
    }
    
    /**
     * 获取插值后的旋转
     * @param alpha 插值因子（0-1）
     */
    getInterpolatedRotation(alpha: number): Vec3 {
        if (!this.enableRotationInterpolation || alpha === 0) {
            return this.rotation.clone();
        }
        
        // 旋转插值（需要处理角度环绕问题）
        return new Vec3(
            this.lerpAngle(this.previousRotation.x, this.rotation.x, alpha),
            this.lerpAngle(this.previousRotation.y, this.rotation.y, alpha),
            this.lerpAngle(this.previousRotation.z, this.rotation.z, alpha)
        );
    }
    
    /**
     * 获取插值后的缩放
     * @param alpha 插值因子（0-1）
     */
    getInterpolatedScale(alpha: number): Vec3 {
        if (!this.enableScaleInterpolation || alpha === 0) {
            return this.scale.clone();
        }
        
        return new Vec3(
            this.previousScale.x + (this.scale.x - this.previousScale.x) * alpha,
            this.previousScale.y + (this.scale.y - this.previousScale.y) * alpha,
            this.previousScale.z + (this.scale.z - this.previousScale.z) * alpha
        );
    }
    
    /**
     * 角度插值（处理环绕问题）
     * @param from 起始角度
     * @param to 目标角度
     * @param alpha 插值因子
     */
    private lerpAngle(from: number, to: number, alpha: number): number {
        // 计算最短角度差
        let delta = to - from;
        
        // 处理 360 度环绕
        while (delta > 180) delta -= 360;
        while (delta < -180) delta += 360;
        
        return from + delta * alpha;
    }
    
    /**
     * 获取完整的插值变换
     */
    getInterpolatedTransform(alpha: number): {
        position: Vec3;
        rotation: Vec3;
        scale: Vec3;
    } {
        return {
            position: this.getInterpolatedPosition(alpha),
            rotation: this.getInterpolatedRotation(alpha),
            scale: this.getInterpolatedScale(alpha)
        };
    }
    
    // ========== 辅助方法 ==========
    
    /**
     * 立即同步（不插值）
     * 用于瞬移等情况
     */
    snapToPosition(x: number, y: number, z: number = 0): void {
        this.position.set(x, y, z);
        this.previousPosition.set(x, y, z);
    }
    
    /**
     * 立即同步（Vec3）
     */
    snapToPositionVec3(position: Vec3): void {
        this.position.set(position);
        this.previousPosition.set(position);
    }
    
    /**
     * 立即同步旋转
     */
    snapToRotation(x: number, y: number, z: number): void {
        this.rotation.set(x, y, z);
        this.previousRotation.set(x, y, z);
    }
    
    /**
     * 立即同步缩放
     */
    snapToScale(x: number, y: number, z: number = 1): void {
        this.scale.set(x, y, z);
        this.previousScale.set(x, y, z);
    }
    
    /**
     * 复制当前状态到上一帧（用于初始化）
     */
    syncPreviousFrame(): void {
        this.previousPosition.set(this.position);
        this.previousRotation.set(this.rotation);
        this.previousScale.set(this.scale);
    }
}

